package cn.opencodes.framework.autoconfigure;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

import cn.opencodes.framework.autoconfigure.properties.AlphaProperties;
import cn.opencodes.framework.autoconfigure.properties.DynamicDataSourceProperties;
import cn.opencodes.framework.autoconfigure.properties.RedissonProperties;
import cn.opencodes.framework.autoconfigure.properties.SwaggerProperties;
import cn.opencodes.framework.core.datasources.DataSourceAspect;
import cn.opencodes.framework.core.interceptor.AccessInterceptor;
import cn.opencodes.framework.core.interceptor.MaliciousInterceptor;
import cn.opencodes.framework.core.log.OperationAspect;
import cn.opencodes.framework.core.redis.RedisDistributedLock;
import cn.opencodes.framework.core.redis.RedisLockAspect;
import cn.opencodes.framework.core.redis.RedisUtils;
import cn.opencodes.framework.core.service.AlphaService;
import cn.opencodes.framework.core.service.DefaultAlphaServiceImpl;
import cn.opencodes.framework.core.shiro.JwtTokenGen;
import cn.opencodes.framework.core.utils.SpringUtils;

import com.google.common.util.concurrent.RateLimiter;

@Configuration
@EnableConfigurationProperties({AlphaProperties.class, DynamicDataSourceProperties.class, SwaggerProperties.class, RedissonProperties.class})
@Import({
    DynamicDataSourceConfiguration.class
   ,ShiroConfiguration.class
   ,MVCAutoConfiguration.class
   ,RedisConfiguration.class
   ,PageHelperConfiguration.class
   ,SwaggerConfiguration.class
   ,RExceptionConfiguration.class
   ,RedissonConfiguration.class
})
public class AlphaAutoConfigure {

	@Bean
	@ConditionalOnMissingBean
	public RedisUtils redisUtils(){
		return new RedisUtils();
	}
	
	@Bean
	@ConditionalOnMissingBean
	public RedisDistributedLock redisDistributedLock(){
		return new RedisDistributedLock();
	}
	
	@Bean
	@ConditionalOnMissingBean
	public SpringUtils springUtils(ApplicationContext applicationContext){
		SpringUtils su = new SpringUtils();
		su.setApplicationContext(applicationContext);
		return su;
	}
	
	@Bean
	@ConditionalOnMissingBean
	public AlphaService commonService(){
		return new DefaultAlphaServiceImpl();
	}
	
	@Bean
	@ConditionalOnMissingBean
	public JwtTokenGen jwtTokenGen(AlphaProperties props){
		JwtTokenGen jwt = new JwtTokenGen();
		jwt.setExpire(props.getExpire());
		jwt.setSecret(props.getSecret());
		return jwt;
	}
	
	@Bean
	@ConditionalOnProperty(name = "spring.malicious.enabled", havingValue = "true")
    @ConditionalOnMissingBean
	public MaliciousInterceptor malicious(AlphaProperties props){
		return new MaliciousInterceptor( RateLimiter.create(props.getRatemax()) );
	}
	
	@Bean
	@ConditionalOnProperty(name = "spring.access.enabled", havingValue = "true")
	@ConditionalOnMissingBean
	public AccessInterceptor access(AlphaProperties props){
		return new AccessInterceptor();
	}
	
	@Bean
	@ConditionalOnMissingBean
	public RedisLockAspect redisLockAspect(){
		return new RedisLockAspect();
	}
	
	@Bean
	@ConditionalOnMissingBean
	public OperationAspect operationAspect(){
		return new OperationAspect();
	}
	
	@Bean
	@ConditionalOnMissingBean
	public DataSourceAspect dataSourceAspect(){
		return new DataSourceAspect();
	}
	
}